﻿using System;

using Silvermoon.Core;
using Silvermoon.OpenGL;
using System.Drawing;
using Silvermoon.Controls;
using Silvermoon.OpenGL.Native;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using Silvermoon.Animations;
using Silvermoon.UI;
using Silvermoon.Controls.Beta;

namespace Testing
{
    public class ListBoxDemo : DemoWindowBase
    {
        private ListBoxBase listBox;
        private FontSprite labelFont;
        private FontSprite boldFont;
        private ItemGroup s1, s2, s3, s4;
        private bool toggle;
        private List<ListBoxItem> lazyItemPool = new List<ListBoxItem>(32);


        public static Texture plusImage, minusImage;

        static ListBoxDemo()
        {
            plusImage = Texture.FromResource("Testing.Images.plus.png", TextureFormat.LuminanceAlpha);
            minusImage = Texture.FromResource("Testing.Images.minus.png", TextureFormat.LuminanceAlpha);
        }

        public ListBoxDemo()
            : base()
        {
           // SetTransition(500, TransitionMask.Bottom, TransitionMask.Bottom | TransitionMask.Fade);
            SetTransition(300, TransitionMask.RotateLeftIn, TransitionMask.RotateLeftOut | TransitionMask.None);

            labelFont = MainWindow.labelFont;
            boldFont = MainWindow.boldFont;
            Controls.Add(new GradientControl(Color.DarkRed));
            ToolbarOpacity = 200;


            TextColor = Color.White;
            Color = Color.Empty;
            listBox = new ListBox();
            listBox.TapItem += (s, e) => listBox.SelectedItem = e.Item;
            listBox.Margin = new Margin(0, 64, 0, 0);
            Controls.Add(listBox);

            listBox.ItemRemoved += (s, e) =>
                {
                    e.Item.Dispose();
                };

            s1 = new ItemGroup { Title = "Group 1", Count = 0, ColumnCount = 3 };
            s2 = new ItemGroup { Title = "Group 2", Count = 0 };
            s3 = new ItemGroup { Title = "Group 3", Count = 0 };
            s4 = new ItemGroup { Title = "Lazy loadings", Count = 36 };


            // if in any of the folowing groups all items are removed, we want to remove the group from the listview also.
            // therefore we trigger changes at the group's item collection and remove the group from the listview if count changes to zero:
            s2.Items.ListChanged += new EventHandler(OnItemCollectionChanged);
            s3.Items.ListChanged += new EventHandler(OnItemCollectionChanged);
            s1.Items.ListChanged += new EventHandler(OnItemCollectionChanged);


            listBox.Items.AddItems(s1, s2, s3, s4);

            // Group 4 is a lazy group which loads it's items only on demand. Therefore we must set the GetItem event of the ItemView
            // to get the item for the collection:
            listBox.GetItem += new EventHandler<ItemGroupEventArgs>(OnGetItem);

            // if an item from a lazy group is no longer visible or otherwise required, the DetachItem event is fired.
            // here we can remove the item and even dispose it here:
            listBox.DetachItem += new EventHandler<DetachItemEventArgs>(OnDetachItem);

            // perform some event when an item in the listbox is tapped:
            this.listBox.TapItem += new EventHandler<ListBoxItemEventArgs>(OnItemTap);

            Label l = new Label { Text = "ListView Demo", Alignment = Alignment.Center, Height = 64, LineAlignment = Alignment.Center, Font = boldFont, TextColor = Color.Gold };
            l.Bounds = new Rectangle(0, 0, Screen.Width, 64);
            Controls.Add(l);


            {
                ContentButton btn = new ToolbarButton();
                btn.Content = plusImage;
                btn.Visible = true;
                toolbar.Buttons.Add(btn);

                btn.Tap += (s, e) =>
                {
                    s2.Items[0].BringIntoView(true);
                    //ListBoxItem item = new SmallItem { Text = DateTime.Now.ToLongTimeString(), Font = boldFont, TextColor = Color.FromArgb(0x68, 0x9a, 0xff) };
                    //int index = Math.Min(4, s1.Items.Count);
                    //s1.InsertAnimated(index, item);
                    ////itemView.Items.InsertAnimated(0, item);
                };

            }
            {
                ContentButton btn = new ToolbarButton();
                btn.Content = minusImage;
                btn.Visible = true;
                toolbar.Buttons.Add(btn);

                btn.Tap += (s, e) =>
                {
                    int x2 = toggle ? 2 : 3;
                    toggle ^= true;
                    //itemView.Items.RemoveAnimated(0);
                    int index = Math.Min(x2, s1.Count - 1);
                    if (s1.Count > index && index >= 0) s1.RemoveAnimated(index);
                    if (s1.Count > x2 + 2) s1.RemoveAnimated(x2 + 2);
                    if (s1.Count > x2 + 3) s1.RemoveAnimated(x2 + 3);
                };
            }

        }


        protected override void Dispose(bool dispose)
        {
            foreach (ListBoxItem item in lazyItemPool)
            {
                item.Dispose();
            }
            lazyItemPool.Clear();
            base.Dispose(dispose);
        }
        /// <summary>
        /// Occurs when a listbox item is tapped.
        /// </summary>
        void OnItemTap(object sender, ListBoxItemEventArgs e)
        {
            if (e.Group != null && e.Item != null)
            {
                if (e.Group != s4)
                {
                    if (e.Group.Count > 1)
                    {
                        e.Group.RemoveAnimated(e.Item);
                    }
                    else
                    {
                        e.Group.ListBox.RemoveAnimated(e.Group);
                    }
                }
            }
        }

        /// <summary>
        /// Detaches a lazy loading item from listbox.
        /// </summary>
        void OnDetachItem(object sender, DetachItemEventArgs e)
        {
            if (e.Group != s4) return;
            //if (e.Item != null) e.Item.Dispose();
            ListBoxItem item = e.Item as ListBoxItem;
            if (item != null)
            {
                item.RemoveAnimationStates();
                // add it back to the pool so that it can be reused:
                lazyItemPool.Add(item);
            }
            e.Item = null;
        }

        /// <summary>
        /// Gets the lazy loading items for the listbox .
        /// </summary>
        void OnGetItem(object sender, ItemGroupEventArgs e)
        {
            if (e.Item == null)
            {
                // get an item from the pool and remove it from the pool:
                int index = lazyItemPool.Count - 1;
                ListBoxItem item;
                if (index >= 0)
                {
                    item = lazyItemPool[index];
                    lazyItemPool.RemoveAt(index);
                }
                else
                {
                    item = new ListBoxItem { TextColor = Color.FromArgb(157, 255, 124), Font = boldFont };
                }
                item.Text = "Lazy Item No. " + e.Index;
                e.Item = item;
            }
        }


        void OnItemCollectionChanged(object sender, EventArgs e)
        {
            ItemGroup group = sender as ItemGroup;
            if (group.Items.Count == 0)
            {
                group.ListBox.RemoveAnimated(group);
            }
        }

        protected override void OnShowing()
        {
            base.OnShowing();
            AnimatedFill();
        }


        private void AnimatedFill()
        {
            bool x = false;
            for (int i = 0; i < 5; i++)
            {
                // since this is performed within an asynchrone animation, it's possible that the user closed the window, therefore we check here
                // if the window is still shown and abort the operation otherwise:
                if (!Visible) return;

                ListBoxItem item = new ListBoxItem();
                item.TextColor = x ? Color.White : Color.LightGreen;
                x ^= true;
                item.Font = labelFont;
                item.Text = string.Format("Group 2 -  #{0} = {1}", i + 1, (i + 1) * (i));
                s2.AddAnimated(item, (5 - i) * 50);
            }

            x = false;

            int max = 11;
            for (int i = 1; i <= max; i++)
            {
                // since this is performed within an asynchrone animation, it's possible that the user closed the window, therefore we check here
                // if the window is still shown and abort the operation otherwise:
                if (Visible == false) break;

                SmallItem item = new SmallItem();
                item.TextColor = x ? Color.White : Color.LightGreen;
                x ^= true;
                item.Font = labelFont;

                int ix = max - i;
                item.Text = string.Format("{0}", ix + 1, (ix + 1) * (ix));
                s1.InsertAnimated(0, item, 400 + (max - i) * 25);
            }



            x = false;
            for (int i = 0; i < 20; i++)
            {
                // since this is performed within an asynchrone animation, it's possible that the user closed the window, therefore we check here
                // if the window is still shown and abort the operation otherwise:
                if (Visible == false) return;

                ListBoxItem item = new ListBoxItem();
                item.TextColor = x ? Color.White : Color.LightGreen;
                x ^= true;
                item.Font = labelFont;
                item.Text = string.Format("Group 3 -  #{0} = {1}", i + 1, (i + 1) * (i));
                s3.InsertAnimated(0, item, 550 + i * 33);
            }

        }
    }
}
